Skip to content

feat: add daemon mode for persistent MCP connections#5

Closed
cs50victor wants to merge 2 commits intophilschmid:mainfrom
cs50victor:feat/daemon-mode
Closed

feat: add daemon mode for persistent MCP connections#5
cs50victor wants to merge 2 commits intophilschmid:mainfrom
cs50victor:feat/daemon-mode

Conversation

@cs50victor
Copy link
Contributor

@cs50victor cs50victor commented Jan 11, 2026

adds a persistent connection daemon that keeps MCP server processes alive across CLI invocations, enabling stateful workflows without reconnection overhead.

  • mcp-cli daemon start|stop|status - manage daemon lifecycle
  • Tool calls auto-route through daemon when running
  • Falls back to ephemeral mode when daemon is not running
  • Idle timeout evicts unused connections (default: 5 min)
CLI invocation -> Unix socket -> Daemon -> MCP Server Pool
  • MCP_DAEMON_SOCKET - Socket path (default: ~/.mcp-cli/daemon.sock)
  • MCP_DAEMON_IDLE_MS - Idle timeout in ms (default: 300000)

tested

  • bun run lint passes
  • bun run typecheck passes
  • bun run test passes (120/122, 2 pre-existing failures)
  • Manual test: daemon start/stop/status
  • Manual test: stateful persistence with chrome-devtools-mcp

Before vs After

Scenario Without Daemon With Daemon
navigate_pagelist_pages Second call sees about:blank (new browser) Second call sees navigated URL (same browser)
Multi-step workflow Each tool call spawns fresh MCP server All calls share persistent connection
Connection overhead Full server startup per invocation One-time startup, reused across calls
Stateful MCP servers Broken (state lost between calls) Works as expected

Concrete example with chrome-devtools-mcp:

# WITHOUT DAEMON
mcp-cli chrome/navigate_page '{"url": "https://example.com"}'  # → Success
mcp-cli chrome/take_screenshot '{}'                            # → Screenshots about:blank (new instance)

# WITH DAEMON
mcp-cli daemon start
mcp-cli chrome/navigate_page '{"url": "https://example.com"}'  # → Success
mcp-cli chrome/take_screenshot '{}'                            # → Screenshots example.com (same instance)

@philschmid
Copy link
Owner

Interesting idea, but i didn't want to add a daemon as it adds a new command which the mode needs to understand and manage. Did you test your branch? What is the impact of it?

@cs50victor
Copy link
Contributor Author

@philschmid I tested this PR with a few MCPs I use alongside Claude Code, such as chrome-devtools-mcp. It fixes the issue of state not being preserved between tool calls, which is necessary for chaining tool calls in complicated browsing tasks - for example, opening a page, taking a screenshot, navigating to a URL, then clicking a link on the page. If you'd like me to refactor this PR or make any changes to the API, I'm open to doing so.

@philschmid
Copy link
Owner

Interesting MCP servers should be stateless by default. Is the chrome dev tool not stateless? If we want to add this we also need to update hte readme, skill and SI. Can you look at this as well? Once we have all of that i will test it too.

@cs50victor
Copy link
Contributor Author

i've also updated the pr description with commands to reproduce the error i was facing.

@cs50victor
Copy link
Contributor Author

hey @philschmid let me know if there are any changes to make so this goes in.

durandom added a commit to durandom/mcp-cli that referenced this pull request Jan 20, 2026
@philschmid
Copy link
Owner

Hey thank you for the PR. I did some experiments myself and added Daemon support in 0.3.0 full changes here: https://github.com/philschmid/mcp-cli/blob/main/CHANGELOG.md#030---2026-01-22

The Daemon is lazy meaning the first request creates a connection which is hold for 60s (configurable) and is reused for the next request.

@philschmid philschmid closed this Jan 23, 2026
@cs50victor
Copy link
Contributor Author

nice. that's a much more efficient design.

@cs50victor cs50victor deleted the feat/daemon-mode branch January 23, 2026 14:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants